﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace _4Gewinnt
{
    /// <summary>
    /// The GUI for 4gewinnt
    /// </summary>
    public partial class _4gewinnt_GUI : Form
    {
        private Engine playerRed, playerBlue;
        private GameController G;
        private TournamentController T; 

        /// <summary>
        /// The number of token in a row to win (we use 4)
        /// </summary>
        private int ttw = 4;

        /// <summary>
        /// The available engines. INSERT YOUR ENGINE(S) HERE
        /// </summary>
        private Type[] engines = new Type[] { 
            typeof(EngineHuman), 
            typeof(EngineRandy),
            typeof(EngineDagobert),
            typeof(EngineGroup472)
        };

        /// <summary>
        /// Initializes GUI
        /// </summary>
        public _4gewinnt_GUI()
        {
            InitializeComponent();
        }


        /// <summary>
        /// Starts a new game
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Initialize player (create a new engine object for each player)
            initEnginesGame();

            //Start a new game
            G = new GameController(this);
            
            //Red always begins
            G.startGame(playerRed, playerBlue);
        }

        /// <summary>
        /// Start a new tournament
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void newTournamentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Allow only non humans for tournament
            List<Type> nonHumanEngines = new List<Type>();
            foreach (Type engineType in engines)
                if (engineType != typeof(EngineHuman))
                    nonHumanEngines.Add(engineType);

            //Start engine selection GUI
            SelectEnginesTournament_GUI IE = new SelectEnginesTournament_GUI();
            IE.startSelection(nonHumanEngines.ToArray());

            //Read selections
            List<Type> tournamentEngines = IE.SelectedEngines;
            int nRounds = IE.nRounds;
            bool showBoardInGUI = IE.showBoardInGUI;

            //Start new tournament
            T = new TournamentController(this, tournamentEngines.ToArray(), nRounds, showBoardInGUI);
            T.startTournament();
        }


        /// <summary>
        /// Initializes the players: Shows a GUI dialoge to choose engines from.
        /// For each player, a new engine object is created
        /// </summary>
        private void initEnginesGame()
        {
            SelectEnginesOneGame_GUI IE = new SelectEnginesOneGame_GUI(engines);
            IE.ShowDialog();
            playerRed = IE.redPlayer;
            playerBlue = IE.bluePlayer;

            //Show names of current contestants in GUI
            showPlayerNames(playerRed, playerBlue);
        }

        /// <summary>
        /// Shows the names of the current contestants in the GUI
        /// </summary>
        /// <param name="playerRed">The red player</param>
        /// <param name="playerBlue">The blue player</param>
        public void showPlayerNames(Engine playerRed, Engine playerBlue)
        {
            labelPlayerRed.Text = playerRed.ToString();
            labelPlayerBlue.Text = playerBlue.ToString();
            labelPlayerRed.Refresh();
            labelPlayerBlue.Refresh();
        }

        /// <summary>
        /// Switches the active player in the GUI
        /// </summary>
        /// <param name="newActivePlayer">The new active player</param>
        public void showActivePlayer(GameColor newActivePlayer)
        {
            if (newActivePlayer == GameColor.Red)
                panelActivePlayer.BackColor = Color.Red;
            else
                panelActivePlayer.BackColor = Color.Blue;
            panelActivePlayer.Refresh();
        }




        /// <summary>
        /// Prints out a game message in a new line
        /// </summary>
        /// <param name="message">The message to be printed</param>
        public void gameMessage(String message)
        {
            richTextBoxGameMessages.AppendText(message + "\n");
            richTextBoxGameMessages.ScrollToCaret();
            richTextBoxEngineMessages.Refresh();
        }


        /// <summary>
        /// Prints out an engine message in a new line
        /// </summary>
        /// <param name="message">The message to be printed. null means, nothing is printed.</param>
        public void engineMessage(String message)
        {
            if (message != null)
            {
                richTextBoxEngineMessages.AppendText(message + "\n");
                richTextBoxEngineMessages.ScrollToCaret();
                richTextBoxEngineMessages.Refresh();
            }
        }


        /// <summary>
        /// Draws the complete field
        /// </summary>
        /// <param name="G">The current game</param>
        public void drawBoard(GameController G)
        {
            int rows = G.game.Board.Rows;
            int cols = G.game.Board.Cols;
            for (int r = 0; r < rows; r++)
            {
                for (int c = 0; c < cols; c++)
                {
                    drawField(r, c, G.game.Board.playerAt(r, c), false);
                }
            }
            tableLayoutPanelGrid.Refresh();
        }


        /// <summary>
        /// Marks the winning tokes of color token
        /// </summary>
        /// <param name="winningPosition">The coordinates of the winning tokes</param>
        /// <param name="winningColor">The winning color</param>
        /// <param name="G">The current game</param>
        public void drawWinningPosition(GameController G, int[,] winningPosition, GameColor winningColor)
        {
            for (int i = 0; i < ttw; i++)
            {
                drawField(
                    winningPosition[i, 0],
                    winningPosition[i, 1],
                    G.game.ActivePlayer,
                    true
                    );
            }
        }

        /// <summary>
        /// Draws a field with color <paramref name="player"/>. 
        /// If a field gets drawn black then something went wrong
        /// </summary>
        /// <param name="r">The row</param>
        /// <param name="c">The column</param>
        /// <param name="player">The token to be drawn</param>
        /// <param name="winningPosition">True, if winning position shall be drawn
        /// (with slightly different color)</param>
        private void drawField(int r, int c, GameColor player, bool winningPosition)
        {
            //determine fill color
            Color color;
            switch (player)
            {
                case GameColor.Red:
                    color = Color.Red;
                    if (winningPosition)
                        color = Color.DarkRed;
                    break;
                case GameColor.Blue:
                    color = Color.Blue;
                    if (winningPosition)
                        color = Color.DarkBlue;
                    break;
                case GameColor.Empty:
                    color = Color.White;
                    if (winningPosition)
                        color = Color.Black;
                    break;
                default:
                    color = Color.Black;
                    break;
            }

            //apply fill color
            if (r == 0 && c == 0)
                panel00.BackColor = color;
            if (r == 0 && c == 1)
                panel01.BackColor = color;
            if (r == 0 && c == 2)
                panel02.BackColor = color;
            if (r == 0 && c == 3)
                panel03.BackColor = color;
            if (r == 0 && c == 4)
                panel04.BackColor = color;
            if (r == 0 && c == 5)
                panel05.BackColor = color;
            if (r == 0 && c == 6)
                panel06.BackColor = color;
            if (r == 1 && c == 0)
                panel10.BackColor = color;
            if (r == 1 && c == 1)
                panel11.BackColor = color;
            if (r == 1 && c == 2)
                panel12.BackColor = color;
            if (r == 1 && c == 3)
                panel13.BackColor = color;
            if (r == 1 && c == 4)
                panel14.BackColor = color;
            if (r == 1 && c == 5)
                panel15.BackColor = color;
            if (r == 1 && c == 6)
                panel16.BackColor = color;
            if (r == 2 && c == 0)
                panel20.BackColor = color;
            if (r == 2 && c == 1)
                panel21.BackColor = color;
            if (r == 2 && c == 2)
                panel22.BackColor = color;
            if (r == 2 && c == 3)
                panel23.BackColor = color;
            if (r == 2 && c == 4)
                panel24.BackColor = color;
            if (r == 2 && c == 5)
                panel25.BackColor = color;
            if (r == 2 && c == 6)
                panel26.BackColor = color;
            if (r == 3 && c == 0)
                panel30.BackColor = color;
            if (r == 3 && c == 1)
                panel31.BackColor = color;
            if (r == 3 && c == 2)
                panel32.BackColor = color;
            if (r == 3 && c == 3)
                panel33.BackColor = color;
            if (r == 3 && c == 4)
                panel34.BackColor = color;
            if (r == 3 && c == 5)
                panel35.BackColor = color;
            if (r == 3 && c == 6)
                panel36.BackColor = color;
            if (r == 4 && c == 0)
                panel40.BackColor = color;
            if (r == 4 && c == 1)
                panel41.BackColor = color;
            if (r == 4 && c == 2)
                panel42.BackColor = color;
            if (r == 4 && c == 3)
                panel43.BackColor = color;
            if (r == 4 && c == 4)
                panel44.BackColor = color;
            if (r == 4 && c == 5)
                panel45.BackColor = color;
            if (r == 4 && c == 6)
                panel46.BackColor = color;
            if (r == 5 && c == 0)
                panel50.BackColor = color;
            if (r == 5 && c == 1)
                panel51.BackColor = color;
            if (r == 5 && c == 2)
                panel52.BackColor = color;
            if (r == 5 && c == 3)
                panel53.BackColor = color;
            if (r == 5 && c == 4)
                panel54.BackColor = color;
            if (r == 5 && c == 5)
                panel55.BackColor = color;
            if (r == 5 && c == 6)
                panel56.BackColor = color;

            
        }

        #region Human control
        private void buttonMove1_Click(object sender, EventArgs e)
        {
            if (G != null && G.activePlayer.IsHuman)
                ((EngineHuman)G.activePlayer).receiveMoveFromGUI(0);
        }

        private void buttonMove2_Click(object sender, EventArgs e)
        {
            if (G != null && G.activePlayer.IsHuman)
                ((EngineHuman)G.activePlayer).receiveMoveFromGUI(1);
        }

        private void buttonMove3_Click(object sender, EventArgs e)
        {
            if (G != null && G.activePlayer.IsHuman)
                ((EngineHuman)G.activePlayer).receiveMoveFromGUI(2);
        }

        private void buttonMove4_Click(object sender, EventArgs e)
        {
            if (G != null && G.activePlayer.IsHuman)
                ((EngineHuman)G.activePlayer).receiveMoveFromGUI(3);
        }

        private void buttonMove5_Click(object sender, EventArgs e)
        {
            if (G != null && G.activePlayer.IsHuman)
                ((EngineHuman)G.activePlayer).receiveMoveFromGUI(4);
        }

        private void buttonMove6_Click(object sender, EventArgs e)
        {
            if (G != null && G.activePlayer.IsHuman)
                ((EngineHuman)G.activePlayer).receiveMoveFromGUI(5);
        }

        private void buttonMove7_Click(object sender, EventArgs e)
        {
            if (G != null && G.activePlayer.IsHuman)
                ((EngineHuman)G.activePlayer).receiveMoveFromGUI(6);
        }
        #endregion

        /// <summary>
        /// Kill the process (if a human player was active, the while-loop has to be killed. Dirty but works)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _4gewinnt_GUI_FormClosed(object sender, FormClosedEventArgs e)
        {
            Environment.Exit(0);
        }







    }
}
